// N1Thread.h: interface for the N1Thread class.
//
//////////////////////////////////////////////////////////////////////

#ifndef N1THREAD_H_2009_09_23
#define N1THREAD_H_2009_09_23

#include "N1Lib.h"

class N1Dictionary;
class N1AutoreleasePool;


class N1Thread : public N1Object {
protected:
    static N1UInt32 m_nCount;

#define N1ThreadMaxTLS    5
    N1UInt32        m_nLastTLS;
    N0Pointer       m_TLS[N1ThreadMaxTLS];

#ifdef WINDOWS
    HANDLE          m_hThread;
    N1UInt32        m_nThreadId;
#endif

	N1Thread();

#ifdef WINDOWS
    friend DWORD WINAPI N1ThreadProc(LPVOID lpParameter);
    friend class N1AutoreleasePool;
#endif
    static N1AutoreleasePool* getThreadLastAutoreleasePool();
    static N1AutoreleasePool* setThreadLastAutoreleasePool(N1AutoreleasePool* newPool);

public:
	virtual ~N1Thread();

    pcstr name() const ;

    static void detachNewThread(N1DelegatePtr<void, void*> *ptr, void* p1);

    static void detachNewThread(void(*function)(void*), void* p1);

    static void sleep(N1UInt32 ms);

    static bool isMultiThreaded();
    static void exit();

    static N1Thread* currentThread();

    N1Dictionary* getThreadDictionary();

    uint32 addTLS();
    void*  getTLS(uint32 index);
    void   setTLS(uint32 index, void* data);
};

void N1ThreadInitialize();

template<typename T>
class N1TLS {
    N1UInt32  m_index;
public:
    N1TLS()
    {
        m_index = N1Thread::currentThread()->addTLS();
    };

    N1TLS(T value)
    {
        m_index = N1Thread::currentThread()->addTLS();
        N1Thread::currentThread()->setTLS(m_index, (void*)value);
    };

    operator T()
    {
        return (T)N1Thread::currentThread()->getTLS(m_index);
    };

    bool operator==(T value)
    {
        return ((T)N1Thread::currentThread()->getTLS(m_index) == value);
    };

    const T& operator=(const T &value)
    {
        N1Thread::currentThread()->setTLS(m_index, (void*)value);
        return value;
    };
};


#endif //N1THREAD_H_2009_09_23
